package org.hismig.shard.hibernate;

import java.sql.SQLException;
import java.util.Properties;

import javax.sql.DataSource;

import org.hibernate.ConnectionReleaseMode;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.hibernate.cfg.Environment;
import org.hibernate.classic.Session;
import org.hismig.cfg.DBConnection;
import org.hismig.partition.IDynamicPartition;
import org.hismig.utils.CheckTool;
import org.hismig.utils.JDBCTool;

/**
 * @declare: //TODO <br />
 *           This class created by Vansion.Hopihit on 2012-9-6 <br />
 *           <a href="mailto:vansionhopihit@gmail.com">Contact Me</a>
 * @version 1.0
 * @author Vansion.Hopihit
 * 
 */
public class SessionFactoryWrapper {

	private SessionFactory sessionFactory;

	private long createTime;
	private long invokeTimes;
	private long lastInvokeTime;

	private DBConnection dbConnection;

	private DataSource dataSource;

	public SessionFactoryWrapper() {
		this.lastInvokeTime = System.currentTimeMillis();
	}

	public SessionFactoryWrapper(DBConnection dbConnection,
			String[] mappingLocations, Properties hibernateProperties) {
		CheckTool.checkNotNull(dbConnection);
		CheckTool.checkNotNull(mappingLocations);
		CheckTool.checkArgument(mappingLocations.length > 0);

		this.dbConnection = dbConnection;

		this.sessionFactory = getSessionFactory(mappingLocations,
				hibernateProperties);
		CheckTool.checkNotNull(sessionFactory);

		this.dataSource = JDBCTool.getDataSource(dbConnection);
		CheckTool.checkNotNull(dataSource);

		createTime = System.currentTimeMillis();
	}

	private SessionFactory getSessionFactory(String[] mappingLocations,
			Properties hibernateProperties) {

		Configuration configuration = new Configuration();

		configuration.setProperty(Environment.RELEASE_CONNECTIONS,
				ConnectionReleaseMode.ON_CLOSE.toString());

		if (null != hibernateProperties) {
			configuration.addProperties(hibernateProperties);
		}

		for (String mappingLocation : mappingLocations) {
			configuration.addInputStream(getClass().getClassLoader()
					.getResourceAsStream(mappingLocation));
		}

		return configuration.buildSessionFactory();

	}

	public Session openSession() throws SQLException {

		invokeTimes++;
		lastInvokeTime = System.currentTimeMillis();

		return sessionFactory.openSession(dataSource.getConnection());

	}

	public boolean judgeCondition(DBConnection dbConnection) {
		if (this.dbConnection.getParamByName(IDynamicPartition.KEY_SELECTION)
				.equals(dbConnection
						.getParamByName(IDynamicPartition.KEY_SELECTION))) {
			return true;
		}

		return false;
	}

	public long getCreateTime() {
		return createTime;
	}

	public long getInvokeTimes() {
		return invokeTimes;
	}

	public long getLastInvokeTime() {
		return lastInvokeTime;
	}

	public void close() {
		if (null != sessionFactory) {
			sessionFactory.close();
			sessionFactory = null;
		}

		JDBCTool.closeQuietly(dataSource);

		dbConnection = null;
		createTime = 0L;
		invokeTimes = 0L;
		lastInvokeTime = 0L;
	}
}
